/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.oai.metadataRepository;

import cz.mzk.oai.metadataRepository.analysis.marcxml.MarcxmlFilesAnalyzer;
import cz.mzk.oai.metadataRepository.harvest.AlephExportHarvester;
import cz.mzk.oai.metadataRepository.harvest.MarcHarvester;
import cz.mzk.oai.metadataRepository.harvest.OAIHarvester;
import cz.mzk.oai.metadataRepository.metadata.DateStamp;
import cz.mzk.oai.metadataRepository.metadata.MetadataFormat;
import cz.mzk.oai.metadataRepository.repository.MetadataBase;
import cz.mzk.oai.metadataRepository.repository.MetadataCollection;
import cz.mzk.oai.metadataRepository.repository.Repository;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author martin
 */
public class Main {

    //TODO: zjistit, proc se vytvari nekolikrat repository.log
    static String alephBackupDir;
    static String harvestLog;
    static Properties properties;
    static String usage = "Usage: java -jar fileHarvester.jar devel|production|local \n"
            + "harvest_aleph_new|harvest_aleph_all|\n"
            + "print|print_sets|\n"
            + "recreate_ese [collection name|ALL]|\n"
            + "recreate_oai_dc [collection name|ALL]|\n"
            + "analyze marcxml [datafield856] |ese [dc_language|europeana_isShownBy|europeana_isShownAt|europeana_object] |\n"
            + "validate [marcxml|ese|oai_dc|ALL]";

    private static void init(String[] args) {
        File propertiesFile = new File(args[0] + ".properties");
        //System.out.println("properties file: " + propertiesFile.getAbsolutePath());
        try {
            InputStreamReader reader = new FileReader(propertiesFile);
            properties = new Properties();
            properties.load(reader);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Could not find file " + propertiesFile.getAbsolutePath(), ex);
            System.err.println(usage);
            return;
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Error while reading file " + propertiesFile.getAbsolutePath(), ex);
            return;
        }
        alephBackupDir = properties.getProperty("repositoryManager.AlephExportHarvester.exportDir");
        harvestLog = properties.getProperty("repositoryManager.harvest.log");
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println(usage);
            return;
        }
        init(args);

        String action = args[1];
        //String action = "harvest_aleph_new";
        //String action = "print";
        //String action = "test";
        //String action = "validate_ese";
        //String action = "validate_marc21";
        //String action = "validate_oai_dc";
        //String action = "harvest_aleph_all";


        if ("harvest_aleph_new".equals(action)) {
            harvestAleph(DateStamp.dateStampWeekAgo());
        } else if ("harvest_aleph_all".equals(action)) {
            harvestAleph(null);
        } else if ("print".equals(action)) {
            printCollections();
        } else if ("print_sets".equals(action)) {
            printSets();
        } else if ("recreate_ese".equals(action)) {
            if (args.length != 3) {
                System.out.println("Specify collection (or ALL)");
            } else {
                String collectionName = args[2];
                Repository repository = Repository.instanceOf(properties);
                if ("ALL".equals(collectionName)) {
                    repository.recreateRecords(true, false);
                } else {
                    repository.recreateRecords(collectionName, true, false);
                }
                repository.close();
            }
        } else if ("recreate_oai_dc".equals(action)) {
            if (args.length != 3) {
                System.out.println("Specify collection (or ALL)");
            } else {
                String collectionName = args[2];
                Repository repository = Repository.instanceOf(properties);
                if ("ALL".equals(collectionName)) {
                    repository.recreateRecords(false, true);
                } else {
                    repository.recreateRecords(collectionName, false, true);
                }
                repository.close();
            }
        } else if ("analyze".equals(action)) {
            if (args.length == 2) {
                System.err.println("Specify metadata format");
            }
            if (args.length == 3) {
                System.err.println("Specify analysis type");
            } else {
                String metadataFormat = args[2];
                String analysisType = args[3];
                if (metadataFormat.equals("marcxml")) {
                    if (analysisType.equals("datafield856")) {
                        analyze856();
                    } else {
                        System.err.println("No such analysis type '" + analysisType + "' for " + metadataFormat);
                    }
                } else if (metadataFormat.equals("ese")) {
                    if (analysisType.equals("dc_language")) {
                        analyzeEseDcLanguage();
                    } else if (analysisType.equals("europeana_isShownBy")) {
                        analyzeEseEuropeanaIsShownBy();
                    } else if (analysisType.equals("europeana_isShownAt")) {
                        analyzeEseEuropeanaIsShownAt();
                    } else if (analysisType.equals("europeana_object")) {
                        analyzeEseEuropeanaObject();
                    } else {
                        System.err.println("No such analysis type '" + analysisType + "' for " + metadataFormat);
                    }
                } else {
                    System.err.println("No such metadata format '" + metadataFormat + "'");
                }
            }
        } else if ("validate".equals(action)) {
            if (args.length != 3) {
                System.err.println("Specify format being validated (or ALL)");
            } else {
                String validatedFormat = args[2];
                if (validatedFormat.equals("ALL")) {
                    validate(MetadataFormat.marc21);
                    validate(MetadataFormat.ese);
                    validate(MetadataFormat.oai_dc);
                } else if (validatedFormat.equals("marcxml")) {
                    validate(MetadataFormat.marc21);
                } else if (validatedFormat.equals("ese")) {
                    validate(MetadataFormat.ese);
                } else if (validatedFormat.equals("oai_dc")) {
                    validate(MetadataFormat.oai_dc);
                } else {
                    System.err.println("No such format '" + args[2] + "'");
                }
            }
        } else if ("test".equals(action)) {
            //tady muzu zkouset ruzne veci
            //validace
            //marc21
            //            File dir = new File("/home/martin/tmp/metadata-collections/mollMapsAfter1800/marc21");
            //            List<String> files = Tools.readFiles(dir);
            //            if (files == null) {
            //                System.err.println("files == null");
            //            } else {
            //                System.out.println("files != null");
            //            }
            //            File testFile = new File("/home/martin/tmp/metadata-collections/mollMapsError1800/marc21/oai%3Aaleph.mzk.cz%3AMZK03-001028947.xml");
            //            MetadataValidator.instanceOf().isValid(testFile, MetadataFormat.marc21, true);
            //            File testDir = new File("/home/martin/tmp/metadata-collections/mollMapsBefore1800/marc21");
            //            MetadataValidator.instanceOf().validateDir(testDir, MetadataFormat.marc21,true);
            //ese
            // File testFile = new File("/home/martin/tmp/metadata-collections/schramVeduteBefore1800/ese/oai%3Aaleph.mzk.cz%3AMZK03-001076317.xml");
            // MetadataValidator.instanceOf().isValid(testFile, MetadataFormat.ese, true);
            //             File testDir = new File("/home/martin/tmp/metadata-collections/schramVeduteBefore1800/ese");
            //            MetadataValidator.instanceOf().validateDir(testDir, MetadataFormat.ese,true);
            //tranformace ese - reseni dvojitych object
            //Test.downloadAndReadFromUrl("http://aleph.mzk.cz/OAI?verb=GetRecord&metadataPrefix=marc21&identifier=oai:aleph.mzk.cz:MZK03-001076317");
            //transformace schramVedute do ese and validation
                /*try {
            String marcFilename = "/home/martin/tmp/metadata-collections/schramVeduteBefore1800/marc21/oai%3Aaleph.mzk.cz%3AMZK03-001076317.xml";
            String eseFilename = "/home/martin/tmp/metadata-collections/schramVeduteBefore1800/ese/oai%3Aaleph.mzk.cz%3AMZK03-001076317.xml";
            MetadataTransformer.transform(marcFilename, eseFilename, Main.marc2ese_schramVedute);
            //MetadataTransformer.transform(marcFilename, eseFilename, Main.marc2ese_schramPortraits);
            boolean valid = MetadataValidator.instanceOf().isValid(new File(eseFilename), MetadataFormat.ese, true);
            if (valid) {
            System.out.println("VALID");
            } else {
            System.out.println("INVALID");
            }
            } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }*/
            /*
            String prefix = "/home/martin/oai/aleph_exports/mzk03-";
            String date = "20100707";
            String inFile = prefix + date + ".m21";
            String outFilePrefix = prefix + date + ".marcxml-";
            try {
            AlephExportHarvester.readMarcExample(inFile, outFilePrefix,false);
            } catch (DocumentException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
             */
            //oprava ese, testovani transformaci
                /*  try {
            String marcFile = "/home/martin/tmp/transformations/in-marc.xml";
            String eseFile = "/home/martin/tmp/transformations/out-ese.xml";
            String marc2ese_mollMaps = "/home/martin/dev/NetBeansProjects/repositoryManager/src/cz/mzk/oai/xslt/marc2ese-schramPortraits.xsl";
            MetadataTransformer.transform(marcFile, eseFile, marc2ese_mollMaps);
            } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }*/
            //analyze040a("schramPortraitsBefore1800");
            //analyze040a("schramPortraitsAfter1800");
                /*Repository repository = Repository.instanceOf(properties);
            repository.recreateRecords("schramPortraitsBefore1800", true, false);
            repository.close();*/

            /*
            String collectionName = "schramPortraitsAfter1800";
            String before = "schramPortraitsBefore1800";
            String after = "schramPortraitsAfter1800";

            System.out.println("dc:language:");
            analyzeEseDcLanguage(before);
            analyzeEseDcLanguage(after);
             */
//            System.out.println("isShownBy:");
//            analyzeEseEuropeanaIsShownBy(collectionName);
//            System.out.println("isShownAt:");
//            analyzeEseEuropeanaIsShownAt(collectionName);
//            System.out.println("object:");
//            analyzeEseEuropeanaObject(collectionName);

            MarcxmlFilesAnalyzer.manuscriptTest("/home/martin/oai/Repository/generalMzk03Before1800/marc21");
            MarcxmlFilesAnalyzer.manuscriptTest("/home/martin/oai/Repository/generalMzk03After1800/marc21");
            MarcxmlFilesAnalyzer.manuscriptTest("/home/martin/oai/Repository/generalMzk03Error1800/marc21");

            /*
            try {
            AlephExports exports = new AlephExports(new File("/home/martin/tmp/alucard-aleph-backups"));
            List<AlephExport> exportList = exports.getSortedExports(null, null);
            for (AlephExport export : exportList) {
            System.out.println(export.getDateStamp());
            }
            } catch (CannotReadDirectoryException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
             */
            //            Repository repository = Repository.instanceOf(properties);
            //            File outFile = new File("/home/martin/tmp/transformationTable");
            //            Converter.createTransformationTable(repository, outFile);
            //            try {
            //                Converter converter = new Converter(new File("/home/martin/tmp/transformationTable"));
            //                String signature = converter.convertSysno("001042910");
            //                System.out.println("signature: " + signature);
            //            } catch (FileNotFoundException ex) {
            //                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            //            } catch (IOException ex) {
            //                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            //            }
                /* try {//TODO: transformovat odpoved OAI do content checker import format
            String oaiResponse2Import = "/home/martin/dev/NetBeansProjects/repositoryManager/src/cz/mzk/oai/xslt/oaiResp2Import.xsl";
            String inXml = "/home/martin/tmp/oaiResult.xml";
            String outXml = "/home/martin/tmp/import-example.xml";
            MetadataTransformer.transform(inXml, outXml, oaiResponse2Import);
            } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }*/
        } else {
            System.out.println(usage);
        }

    }

    public static void printCollections() {
        Repository repository = Repository.instanceOf(properties);
        System.out.println(repository.toString());
        repository.close();
    }

    /**
     * harvests items in aleph that have been created/edited from 'from' until now
     * @param from
     */
    public static void harvestAleph(DateStamp from) {
        //harvestAlephFromOai(from);
        harvestAlephFromExports(from, MetadataBase.MZK01);
        harvestAlephFromExports(from, MetadataBase.MZK03);//TODO: uncomment
    }

    private static void harvestAlephFromOai(DateStamp from) {
        Repository repository = Repository.instanceOf(properties);
        try {
            URL url = new URL("http://aleph.mzk.cz/OAI");
            String set = "MZK03";
            MarcHarvester alephHarvester = new OAIHarvester(url, set, repository, harvestLog);
            alephHarvester.harvestAndUpdate(from, null, true);
        } catch (MalformedURLException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            repository.close();
        }
    }

    private static void harvestAlephFromExports(DateStamp from, MetadataBase base) {
        Repository repository = Repository.instanceOf(properties);
        AlephExportHarvester harvester = new AlephExportHarvester(base, new File(alephBackupDir), repository, harvestLog);
        harvester.harvestAndUpdate(from, null, true);
        repository.close();
    }

    private static void analyze856() {
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            col.analyzeDatafield856();
            System.out.println("------------------------------------");
        }
        repository.close();
    }

    private static void analyze040a(String collectionName) {
        if (collectionName == null) {
            throw new NullPointerException("collectionName");
        }
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            if (collectionName.equals(col.getName())) {
                col.analyzeDatafield040a();
            }
        }
        repository.close();
    }

    private static void analyzeEseDcLanguage(String collectionName) {
        if (collectionName == null) {
            analyzeEseDcLanguage();
        }
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            if (col.getName().equals(collectionName)) {
                col.analyzeEseDcLanguage();
            }
        }
        repository.close();
    }

    private static void analyzeEseDcLanguage() {
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            col.analyzeEseDcLanguage();
            System.out.println("------------------------------------");
        }
        repository.close();
    }

    private static void analyzeEseEuropeanaIsShownBy(String collectionName) {
        if (collectionName == null) {
            analyzeEseEuropeanaIsShownBy();
        }
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            if (col.getName().equals(collectionName)) {
                col.analyzeEseEuropeanaIsShownBy();
            }
        }
        repository.close();
    }

    private static void analyzeEseEuropeanaIsShownBy() {
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            col.analyzeEseEuropeanaIsShownBy();
            System.out.println("------------------------------------");
        }
        repository.close();
    }

    private static void analyzeEseEuropeanaIsShownAt(String collectionName) {
        if (collectionName == null) {
            analyzeEseEuropeanaIsShownAt();
        }
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            if (col.getName().equals(collectionName)) {
                col.analyzeEseEuropeanaIsShownAt();
            }
        }
        repository.close();
    }

    private static void analyzeEseEuropeanaIsShownAt() {
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            col.analyzeEseEuropeanaIsShownAt();
            System.out.println("------------------------------------");
        }
        repository.close();
    }

    private static void analyzeEseEuropeanaObject(String collectionName) {
        if (collectionName == null) {
            analyzeEseEuropeanaObject();
        }
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            if (col.getName().equals(collectionName)) {
                col.analyzeEseEuropeanaObject();
            }
        }
        repository.close();
    }

    private static void analyzeEseEuropeanaObject() {
        Repository repository = Repository.instanceOf(properties);
        for (MetadataCollection col : repository.getCollections()) {
            col.analyzeEseEuropeanaObject();
            System.out.println("------------------------------------");
        }
        repository.close();
    }

    public static void printSets() {
        Repository repository = Repository.instanceOf(properties);
        repository.printSets();
        repository.close();
    }

    public static void validate(MetadataFormat format) {
        Repository repository = Repository.instanceOf(properties);
        repository.validateMetadata(format);
        repository.close();
    }
}
